#ifndef __WIZ_ALGEBRA_MATRIX43_HPP__SHANHAOBO_19800429__
#define __WIZ_ALGEBRA_MATRIX43_HPP__SHANHAOBO_19800429__

#include "./WizAlgebraMatrix43Storage.hpp"
#include "./WizAlgebraMatrix43Template.hpp"

namespace Wiz
{
    namespace Matrix43
    {
        namespace RowMajor
        {
            //////////////////////////////////////////////////////////////
            template<typename ElementT>
            struct Type : public ::Wiz::Matrix43::Template::Type<ElementT, Type<ElementT>, ::Wiz::Matrix43::RowMajor::Method::Type<Type<ElementT> >, ::Wiz::Matrix43::RowMajor::Storage::Type<ElementT> >
            {
                typedef ::Wiz::Matrix43::RowMajor::Storage::Type<ElementT>                           tStorage;
                typedef ::Wiz::Matrix43::RowMajor::Method::Type<Type<tElement>>             tMethod;
                typedef ::Wiz::Matrix43::Template::Type<ElementT, Type, tMethod, tStorage>  tSuper;
                //////////////////////////////////////////////////////////
                typedef Type<tElement>                                                  tThis;
                typedef tThis                                                           tCore;
                typedef ::Wiz::Matrix22::RowMajor::Type<tElement>                       tMatrix22;
                typedef ::Wiz::Matrix33::RowMajor::Type<tElement>                       tMatrix33;
                //////////////////////////////////////////////////////////
                Type()
                {}
                Type(
                    const tElement& E00, const tElement& E01, const tElement& E02, const tElement& E03,
                    const tElement& E10, const tElement& E11, const tElement& E12, const tElement& E13,
                    const tElement& E20, const tElement& E21, const tElement& E22, const tElement& E23,
                    const tElement& E30, const tElement& E31, const tElement& E32, const tElement& E33
                    )
                {
                    tStorage::Set(E00, E01, E02, E03, E10, E11, E12, E13, E20, E21, E22, E23, E30, E31, E32, E33);
                }
                Type(const tElement& InEle)
                {
                    tStorage::Set(InEle);
                }
                Type(const tStorage& InMat)
                {
                    tStorage::Set(InMat);
                }
                ////////////////////////////////////////////////////////////////
                WIZ_INLINE ::Wiz::Void::Type GetRow(tVector4& OutVec4, ::Wiz::UInt::In Row) const
                {
                    tStorage::GetRow(OutVec4.x, OutVec4.y, OutVec4.z, OutVec4.w, Row);
                }
                WIZ_INLINE ::Wiz::Void::Type GetCol(tVector4& OutVec4, ::Wiz::UInt::In Col) const
                {
                    tStorage::GetCol(OutVec4.x, OutVec4.y, OutVec4.z, OutVec4.w, Col);
                }

                WIZ_INLINE ::Wiz::Void::Type GetRow(tElement& OutX, tElement& OutY, tElement& OutZ, tElement& OutW, ::Wiz::UInt::In Row) const
                {
                    tStorage::GetRow(OutX, OutY, OutZ, OutW, Row);
                }
                WIZ_INLINE ::Wiz::Void::Type GetCol(tElement& OutX, tElement& OutY, tElement& OutZ, tElement& OutW, ::Wiz::UInt::In Col) const
                {
                    tStorage::GetCol(OutX, OutY, OutZ, OutW, Col);
                }

                WIZ_INLINE ::Wiz::Void::Type SetRow(::Wiz::UInt::In Row, const tVector4& InVec4)
                {
                    tStorage::SetRow(Row, InVec4.x, InVec4.y, InVec4.z, InVec4.w);
                }
                WIZ_INLINE ::Wiz::Void::Type SetCol(::Wiz::UInt::In Col, const tVector4& InVec4)
                {
                    tStorage::SetCol(Col, InVec4.x, InVec4.y, InVec4.z, InVec4.w);
                }

                WIZ_INLINE ::Wiz::Void::Type SetRow(::Wiz::UInt::In Row, const tElement& InX, const tElement& InY, const tElement& InZ, const tElement& InW)
                {
                    tStorage::SetRow(Row, InX, InY, InZ, InW);
                }
                WIZ_INLINE ::Wiz::Void::Type SetCol(::Wiz::UInt::In Col, const tElement& InX, const tElement& InY, const tElement& InZ, const tElement& InW)
                {
                    tStorage::SetCol(Col, InX, InY, InZ, InW);
                }
                //////////////////////////////////////////////////////////////////////////
                template<class Matrix33T, int rj, int ri>
                Matrix33T& GetCofactor(Matrix33T& OutCofactor) const
                {
                    return tStorage::GetCofactor<Matrix33T, rj, ri>(OutCofactor, *this);
                }
                ////////////////////////////////////////////////////////////////
            }; /// end of struct Type
        } /// end of namespace RowMajor

        namespace ColMajor
        {
            //////////////////////////////////////////////////////////////
            template<typename ElementT>
            struct Type : public ::Wiz::Matrix43::Template::Type<ElementT, Type<ElementT>, ::Wiz::Matrix43::ColMajor::Method::Type<Type<ElementT> >, ::Wiz::Matrix43::ColMajor::Storage::Type<ElementT> >
            {
                typedef ::Wiz::Matrix43::ColMajor::Storage::Type<ElementT>                  tStorage;
                typedef ::Wiz::Matrix43::ColMajor::Method::Type<Type>                       tMethod;
                typedef ::Wiz::Matrix43::Template::Type<ElementT, Type, tMethod, tStorage>  tSuper;
                //////////////////////////////////////////////////////////
                typedef Type<tElement>                                                  tThis;
                typedef tThis                                                           tCore;
                typedef ::Wiz::Matrix22::RowMajor::Type<tElement>                       tMatrix22;
                typedef ::Wiz::Matrix33::RowMajor::Type<tElement>                       tMatrix33;
                //////////////////////////////////////////////////////////
                Type()
                {}
                Type(
                    const tElement& E00, const tElement& E10, const tElement& E20, const tElement& E30,
                    const tElement& E01, const tElement& E11, const tElement& E21, const tElement& E31,
                    const tElement& E02, const tElement& E12, const tElement& E22, const tElement& E32,
                    const tElement& E03, const tElement& E13, const tElement& E23, const tElement& E33
                    )
                {
                    tStorage::Set(E00, E01, E02, E03, E10, E11, E12, E13, E20, E21, E22, E23, E30, E31, E32, E33);
                }
                Type(const tElement& InEle)
                {
                    tStorage::Set(InEle);
                }
                Type(const tSuper& InMat)
                {
                    tStorage::Set(InMat);
                }
                ////////////////////////////////////////////////////////////////
                WIZ_INLINE ::Wiz::Void::Type GetRow(tVector4& OutVec4, ::Wiz::UInt::In Row) const
                {
                    tStorage::GetRow(OutVec4.x, OutVec4.y, OutVec4.z, OutVec4.w, Row);
                }
                WIZ_INLINE ::Wiz::Void::Type GetCol(tVector4& OutVec4, ::Wiz::UInt::In Col) const
                {
                    tStorage::GetCol(OutVec4.x, OutVec4.y, OutVec4.z, OutVec4.w, Col);
                }

                WIZ_INLINE ::Wiz::Void::Type GetRow(tElement& OutX, tElement& OutY, tElement& OutZ, tElement& OutW, ::Wiz::UInt::In Row) const
                {
                    tStorage::GetRow(OutX, OutY, OutZ, OutW, Row);
                }
                WIZ_INLINE ::Wiz::Void::Type GetCol(tElement& OutX, tElement& OutY, tElement& OutZ, tElement& OutW, ::Wiz::UInt::In Col) const
                {
                    tStorage::GetCol(OutX, OutY, OutZ, OutW, Col);
                }

                WIZ_INLINE ::Wiz::Void::Type SetRow(::Wiz::UInt::In Row, const tVector4& InVec4)
                {
                    tStorage::SetRow(Row, InVec4.x, InVec4.y, InVec4.z, InVec4.w);
                }
                WIZ_INLINE ::Wiz::Void::Type SetCol(::Wiz::UInt::In Col, const tVector4& InVec4)
                {
                    tStorage::SetCol(Col, InVec4.x, InVec4.y, InVec4.z, InVec4.w);
                }

                WIZ_INLINE ::Wiz::Void::Type SetRow(::Wiz::UInt::In Row, const tElement& InX, const tElement& InY, const tElement& InZ, const tElement& InW)
                {
                    tSuper::SetRow(Row, InX, InY, InZ, InW);
                }
                WIZ_INLINE ::Wiz::Void::Type SetCol(::Wiz::UInt::In Col, const tElement& InX, const tElement& InY, const tElement& InZ, const tElement& InW)
                {
                    tStorage::SetCol(Col, InX, InY, InZ, InW);
                }
                //////////////////////////////////////////////////////////////////////////
                template<class Matrix33T, int rj, int ri>
                Matrix33T& GetCofactor(Matrix33T& OutCofactor) const
                {
                    return tStorage::GetCofactor<Matrix33T, rj, ri>(OutCofactor, *this);
                }
                WIZ_INLINE ::Wiz::Void::Type GetTransposeArray(float* OutArray) const
                {
                    OutArray[0] = this->e00; OutArray[1] = this->e01; OutArray[2] = this->e02; OutArray[3] = this->e03;
                    OutArray[4] = this->e10; OutArray[5] = this->e11; OutArray[6] = this->e12; OutArray[7] = this->e13;
                    OutArray[8] = this->e20; OutArray[9] = this->e21; OutArray[10] = this->e22; OutArray[11] = this->e23;
                    OutArray[12] = this->e30; OutArray[13] = this->e31; OutArray[14] = this->e32; OutArray[15] = this->e33;
                }
                ////////////////////////////////////////////////////////////////
            }; /// end of struct Type
        } /// end of namespace ColMajor
    } /// end of namespace Matrix44
} /// end of namespace Wiz

#endif /*__WIZ_ALGEBRA_MATRIX44_HPP__SHANHAOBO_19800429__*/
